<template>
  <div
    :id="previewMainDomId"
    :ref="previewOutRefId"
    class="bg"
    :style="customStyle"
    @scroll="canvasScroll"
  >
    <canvas-opt-bar
      v-if="canvasId==='canvas-main'"
      ref="canvas-opt-bar"
      :terminal="terminal"
      :canvas-style-data="canvasStyleData"
      :back-to-top-btn="backToTopBtnShow"
      @link-export-pdf="downloadAsPDF"
      @back-to-top="backToTop"
    />
    <link-opt-bar
      v-if="linkOptBarShow"
      ref="link-opt-bar"
      :terminal="terminal"
      :canvas-style-data="canvasStyleData"
      @link-export-pdf="downloadAsPDF"
      @back-to-top="backToTop"
    />
    <div
      :id="previewDomId"
      :ref="previewRefId"
      :style="canvasInfoMainStyle"
    >
      <el-row
        v-if="showUnpublishedArea"
        class="custom-position"
      >
        <div style="text-align: center">
          <svg-icon
            icon-class="unpublished"
            style="font-size: 75px"
          />
          <br>
          <span>{{ $t('panel.panel_off') }}</span>
        </div>
      </el-row>
      <el-row
        v-else-if="componentDataShow && componentDataShow.length===0"
        class="custom-position"
      >
        <span v-show="isMainCanvas()">{{ $t('panel.panelNull') }}</span>
      </el-row>
      <div
        v-else
        :id="previewTempDomId"
        :ref="previewTempRefId"
        :style="[canvasInfoTempStyle,screenShotStyle]"
        class="main-class"
        @mouseup="deselectCurComponent"
        @mousedown="handleMouseDown"
      >
        <ComponentWrapper
          v-for="(item, index) in componentDataInfo"
          :key="index"
          ref="viewWrapperChild"
          :config="item"
          :canvas-id="canvasId"
          :source-config="componentData[index]"
          :search-count="searchCount"
          :in-screen="inScreen"
          :terminal="terminal"
          :is-relation="relationFilterIds.includes(item.id)"
          :filters="filterMap[item.propValue && item.propValue.viewId]"
          :screen-shot="screenShot"
          :canvas-style-data="canvasStyleData"
          :show-position="showPosition"
          :user-id="userId"
          @filter-loaded="filterLoaded"
        />
      </div>
    </div>
    <el-dialog
      v-if="pdfExportShow"
      :title="'['+panelInfo.name+']'+$t('panel.pdf_export')"
      :visible.sync="pdfExportShow"
      width="80%"
      :top="'8vh'"
      :destroy-on-close="true"
      class="dialog-css2"
    >
      <span style="position: absolute;right: 70px;top:15px">
        <svg-icon
          icon-class="PDF"
          class="ds-icon-pdf"
        />
        <el-select
          v-model="pdfTemplateSelectedIndex"
          :placeholder="$t('panel.switch_pdf_template')"
          @change="changePdfTemplate()"
        >
          <el-option
            v-for="(item, index) in pdfTemplateAll"
            :key="index"
            :label="item.name"
            :value="index"
          />
        </el-select>
      </span>
      <PDFPreExport
        :snapshot="snapshotInfo"
        :panel-name="panelInfo.name"
        :template-content="pdfTemplateContent"
        @closePreExport="closePreExport"
      />
    </el-dialog>

    <!--视图详情-->
    <el-dialog
      :visible.sync="chartDetailsVisible"
      width="80%"
      class="dialog-css"
      :destroy-on-close="true"
      :show-close="true"
      append-to-body
      top="5vh"
    >
      <span
        v-if="chartDetailsVisible"
        style="position: absolute;right: 70px;top:15px"
      >
        <span v-if="showChartInfoType==='enlarge' && hasDataPermission('export',panelInfo.privileges)&& showChartInfo && showChartInfo.type !== 'symbol-map'">
          <span style="font-size: 12px">
            {{ $t('panel.export_pixel') }}
          </span>
          <el-select
            v-model="pixel"
            style="width: 120px; margin-right: 8px; margin-top: -1px"
            :popper-append-to-body="false"
            size="mini"
          >
            <el-option-group
              v-for="group in pixelOptions"
              :key="group.label"
              :label="group.label"
            >
              <el-option
                v-for="item in group.options"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-option-group>
          </el-select>
          <el-button
            class="el-icon-picture-outline"
            size="mini"
            :disabled="imageDownloading"
            @click="exportViewImg"
          >
            {{ $t('chart.export_img') }}
          </el-button>
        </span>

        <el-button
          v-if="showChartInfoType==='details'&& showChartInfo.dataFrom !== 'template' && hasDataPermission('export',panelInfo.privileges)"
          size="mini"
          :disabled="$store.getters.loadingMap[$store.getters.currentPath]"
          @click="exportExcel"
        >
          <svg-icon
            icon-class="ds-excel"
            class="ds-icon-excel"
          />{{ $t('chart.export') }}Excel
        </el-button>
        <el-button
          v-if="showChartInfoType==='details' && showChartInfo.dataFrom !== 'template' && !userId && hasDataPermission('export',panelInfo.privileges)"
          size="mini"
          :disabled="$store.getters.loadingMap[$store.getters.currentPath]"
          @click="exportSourceDetails"
        >
          <svg-icon
            icon-class="ds-excel"
            class="ds-icon-excel"
          />{{ $t('chart.export_source') }}
        </el-button>
      </span>
      <user-view-dialog
        v-if="chartDetailsVisible"
        ref="userViewDialog-canvas-main"
        :user-id="userId"
        :chart="showChartInfo"
        :chart-table="showChartTableInfo"
        :canvas-style-data="canvasStyleData"
        :open-type="showChartInfoType"
      />
    </el-dialog>
  </div>
</template>

<script>
import { Button } from 'element-ui'
import { getStyle } from '@/components/canvas/utils/style'
import { mapState } from 'vuex'
import ComponentWrapper from './ComponentWrapper'
import { changeStyleWithScale } from '@/components/canvas/utils/translate'
import { uuid } from 'vue-uuid'
import { deepCopy, imgUrlTrans } from '@/components/canvas/utils/utils'
import eventBus from '@/components/canvas/utils/eventBus'
import elementResizeDetectorMaker from 'element-resize-detector'
import CanvasOptBar from '@/components/canvas/components/editor/CanvasOptBar'
import bus from '@/utils/bus'
import { buildFilterMap, buildViewKeyMap, formatCondition, valueValid, viewIdMatch, buildAfterFilterLoaded } from '@/utils/conditionUtil'
import { hasDataPermission } from '@/utils/permission'
import { activeWatermark } from '@/components/canvas/tools/watermark'
import { proxyUserLoginInfo, userLoginInfo } from '@/api/systemInfo/userLogin'
import html2canvas from 'html2canvasde'
import { queryAll } from '@/api/panel/pdfTemplate'
import PDFPreExport from '@/views/panel/export/PDFPreExport'
import { listenGlobalKeyDownPreview } from '@/components/canvas/utils/shortcutKey'
import UserViewDialog from '@/components/canvas/customComponent/UserViewDialog'
import { hexColorToRGBA } from '@/views/chart/chart/util'
import { isMobile } from '@/utils/index'
import LinkOptBar from '@/components/canvas/components/editor/LinkOptBar'

const erd = elementResizeDetectorMaker()
export default {
  components: { LinkOptBar, UserViewDialog, ComponentWrapper, CanvasOptBar, PDFPreExport },
  model: {
    prop: 'show',
    event: 'change'
  },
  props: {
    // 后端截图
    backScreenShot: {
      type: Boolean,
      default: false
    },
    screenShot: {
      type: Boolean,
      default: false
    },
    show: {
      type: Boolean,
      default: false
    },
    showType: {
      type: String,
      required: false,
      default: 'full'
    },
    inScreen: {
      type: Boolean,
      required: false,
      default: true
    },
    activeTab: {
      type: String,
      required: false,
      default: 'none'
    },
    componentData: {
      type: Array,
      required: false,
      default: function() {
        return []
      }
    },
    canvasStyleData: {
      type: Object,
      required: false,
      default: function() {
        return {}
      }
    },
    showPosition: {
      type: String,
      required: false,
      default: 'preview'
    },
    panelInfo: {
      type: Object,
      required: true
    },
    canvasId: {
      type: String,
      require: false,
      default: 'canvas-main'
    },
    userId: {
      type: String,
      require: false
    }
  },
  data() {
    return {
      backToTopBtnShow: false,
      imageDownloading: false,
      chartDetailsVisible: false,
      canvasMain: null,
      tempCanvas: null,
      showChartInfo: {},
      showChartTableInfo: {},
      showChartInfoType: 'details',
      mainHeightCount: null,
      userInfo: null,
      previewMainDomId: 'preview-main-' + this.canvasId,
      previewDomId: 'preview-' + this.canvasId,
      previewRefId: 'preview-ref-' + this.canvasId,
      previewOutRefId: 'preview-out-ref-' + this.canvasId,
      previewTempDomId: 'preview-temp-' + this.canvasId,
      previewTempRefId: 'preview-temp-ref-' + this.canvasId,
      isShowPreview: false,
      panelId: '',
      needToChangeHeight: [
        'top',
        'height'
      ],
      needToChangeWidth: [
        'left',
        'width'
      ],
      needToChangeInnerWidth: [
        'fontSize',
        'activeFontSize',
        'borderWidth',
        'letterSpacing'
      ],
      scaleWidth: '100',
      scaleWidthLay: '100',
      scaleHeight: '100',
      timer: null,
      componentDataShow: [],
      mainWidth: '100%',
      mainHeight: '100%',
      searchCount: 0,
      filterMapCache: {},
      // 布局展示 1.pc pc端布局 2.mobile 移动端布局
      terminal: 'pc',
      buttonFilterMap: null,
      pdfExportShow: false,
      dataLoading: false,
      exporting: false,
      snapshotInfo: '',
      pdfTemplateSelectedIndex: 0,
      pdfTemplateContent: '',
      templateInfo: {},
      pdfTemplateAll: [],
      pixelOptions: [
        {
          label: 'Windows(16:9)',
          options: [
            {
              value: '1920 * 1080',
              label: '1920 * 1080'
            },
            {
              value: '1600 * 900',
              label: '1600 * 900'
            },
            {
              value: '1280 * 720',
              label: '1280 * 720'
            }
          ]
        },
        {
          label: 'MacOS(16:10)',
          options: [
            {
              value: '2560 * 1600',
              label: '2560 * 1600'
            },
            {
              value: '1920 * 1200',
              label: '1920 * 1200'
            },
            {
              value: '1680 * 1050',
              label: '1680 * 1050'
            }
          ]
        }
      ],
      pixel: '1280 * 720'
    }
  },
  computed: {
    linkOptBarShow() {
      return this.canvasId==='canvas-main' && this.canvasStyleData.showPublicLinkButton
    },
    screenShotStatues() {
      return this.exporting || this.screenShot || this.backScreenShot
    },
    mainActiveName() {
      return this.$store.state.panel.mainActiveName
    },
    showUnpublishedArea() {
      if (this.canvasId !== 'canvas-main') {
        return false
      }
      if (this.showPosition === 'edit') {
        return false
      } else if (this.panelInfo && this.panelInfo.showType === 'view') {
        return false
      } else if ((this.mainActiveName === 'PanelMain' && this.activeTab === 'PanelList') || this.showPosition.includes('multiplexing')) {
        return this.panelInfo.status === 'unpublished' && !hasDataPermission('manage', this.panelInfo.privileges)
      } else {
        return this.panelInfo.status === 'unpublished'
      }
    },
    canvasInfoMainStyle() {
      if (this.backScreenShot) {
        return {
          width: '100%',
          height: this.mainHeight
        }
      } else {
        return {
          width: '100%',
          height: '100%'
        }
      }
    },
    canvasInfoTempStyle() {
      if (this.screenShot) {
        return {
          width: '100%',
          height: this.mainHeight
        }
      } else {
        return {
          width: '100%',
          height: '100%'
        }
      }
    },
    customStyle() {
      let style = {
        width: '100%'
      }
      if (this.canvasStyleData.openCommonStyle && this.isMainCanvas()) {
        const styleInfo = this.terminal === 'mobile' && this.canvasStyleData.panel.mobileSetting && this.canvasStyleData.panel.mobileSetting.customSetting
          ? this.canvasStyleData.panel.mobileSetting : this.canvasStyleData.panel
        if (styleInfo.backgroundType === 'image' && typeof (styleInfo.imageUrl) === 'string') {
          style = {
            background: `url(${imgUrlTrans(styleInfo.imageUrl)}) no-repeat`
          }
        } else if (styleInfo.backgroundType === 'color') {
          const colorRGBA = hexColorToRGBA(styleInfo.color, styleInfo.alpha === undefined ? 100 : styleInfo.alpha)
          style = {
            background: colorRGBA
          }
        } else {
          style = {
            background: '#f7f8fa'
          }
        }
      }
      if (this.backScreenShot) {
        style.height = this.mainHeight
      } else {
        style.padding = '0px'
      }
      return style
    },
    screenShotStyle() {
      return this.screenShot ? this.customStyle : {}
    },
    // 此处单独计算componentData的值 不放入全局mapState中
    componentDataInfo() {
      return this.componentDataShow || []
    },
    ...mapState([
      'sourceComponentData',
      'previewCanvasScale',
      'isClickComponent'
    ]),

    searchButtonInfo() {
      const result = this.buildButtonFilterMap(this.$store.state.componentData)
      return result
    },
    filterMap() {
      const result = buildFilterMap(this.componentData)
      Object.keys(result).forEach(ele => {
        if (this.filterMapCache[ele]?.length) {
          result[ele].forEach(itx => {
            const condition = this.filterMapCache[ele].find(item => item.componentId === itx.componentId && itx.cacheObj)
            if (condition) {
              itx.cacheObj = condition.cacheObj
            }
          })
          if (!result[ele].length) {
            result[ele] = this.filterMapCache[ele]
          }
        } else {
          this.filterMapCache[ele] = result[ele]
        }
      })
      if (this.searchButtonInfo && this.searchButtonInfo.buttonExist && !this.searchButtonInfo.autoTrigger && this.searchButtonInfo.relationFilterIds) {
        for (const key in result) {
          if (Object.hasOwnProperty.call(result, key)) {
            let filters = result[key]
            filters = filters.filter(item => !this.searchButtonInfo.relationFilterIds.includes(item.componentId))
            result[key] = filters
          }
        }
      }
      return result
    },
    buttonExist() {
      return this.searchButtonInfo && this.searchButtonInfo.buttonExist
    },
    relationFilterIds() {
      return this.buttonExist && this.searchButtonInfo.relationFilterIds || []
    }
  },
  watch: {
    componentData: {
      handler(newVal, oldVla) {
        this.restore()
      },
      deep: true
    },
    canvasStyleData: {
      handler(newVal, oldVla) {
        this.canvasStyleDataInit()
      },
      deep: true
    },
    mainHeight: {
      handler(newVal, oldVla) {
        this.$nextTick(() => {
          this.reloadWatermark()
        })
      },
      deep: true
    },
    canvasInfoTempStyle: {
      handler(newVal, oldVla) {
        this.$nextTick(() => {
          this.reloadWatermark()
        })
      },
      deep: true
    },
    screenShotStatues: {
      handler(newVal, oldVla) {
        this.reloadWatermark()
      }
    }
  },
  created() {
    // 防止编辑界面销毁键盘事件监听
    if (this.canvasId === 'canvas-main' && !this.showPosition.includes('multiplexing')) {
      listenGlobalKeyDownPreview()
    }
  },
  mounted() {
    this.initWatermark()
    this._isMobile()
    this.initListen()
    this.$store.commit('clearLinkageSettingInfo', false)
    this.canvasStyleDataInit()
    if (this.terminal === 'mobile') {
      this.initMobileCanvas()
    }
    this.canvasId === 'canvas-main' && bus.$on('pcChartDetailsDialog', this.openChartDetailsDialog)
    bus.$on('trigger-search-button', this.triggerSearchButton)
    bus.$on('trigger-reset-button', this.triggerResetButton)
    this.initPdfTemplate()
  },
  beforeDestroy() {
    if (this.$refs[this.previewTempRefId]) {
      erd.uninstall(this.$refs[this.previewTempRefId])
    }
    if (this.$refs[this.previewRefId]) {
      erd.uninstall(this.$refs[this.previewRefId])
    }
    this.canvasMain && erd.uninstall(this.canvasMain)
    this.tempCanvas && erd.uninstall(this.tempCanvas)
    clearInterval(this.timer)
    this.canvasId === 'canvas-main' && bus.$off('pcChartDetailsDialog', this.openChartDetailsDialog)
    bus.$off('trigger-search-button', this.triggerSearchButton)
    bus.$off('trigger-reset-button', this.triggerResetButton)
  },
  methods: {
    reloadWatermark() {
      if (this.screenShotStatues) {
        this.initWatermark('preview-temp-canvas-main')
      } else {
        this.initWatermark()
      }
    },
    filterLoaded(p) {
      buildAfterFilterLoaded(this.filterMap, p)
      this.filterMapCache = {}
      this.getWrapperChildRefs().forEach(item => item.triggerFilterLoaded(p))
    },
    getWrapperChildRefs() {
      return this.$refs['viewWrapperChild']
    },
    getAllWrapperChildRefs() {
      const allChildRefs = []
      const currentChildRefs = this.getWrapperChildRefs()
      if (currentChildRefs && currentChildRefs.length > 0) {
        allChildRefs.push.apply(allChildRefs, currentChildRefs)
      }
      currentChildRefs && currentChildRefs.forEach(subRef => {
        if (subRef?.getType && subRef.getType() === 'de-tabs') {
          const currentTabChildRefs = subRef.getWrapperChildRefs()
          if (currentTabChildRefs && currentTabChildRefs.length > 0) {
            allChildRefs.push.apply(allChildRefs, currentTabChildRefs)
          }
        }
      })
      return allChildRefs
    },

    getCanvasHeight() {
      return this.mainHeightCount
    },
    openChartDetailsDialog(paramInfo) {
      if (this.canvasId === 'canvas-main') {
        this.showChartInfo = paramInfo.showChartInfo
        this.showChartTableInfo = paramInfo.showChartTableInfo
        this.showChartInfoType = paramInfo.showChartInfoType
        this.chartDetailsVisible = true
      }
    },
    initWatermark(waterDomId = 'preview-main-canvas-main') {
      if (this.panelInfo.watermarkInfo && this.canvasId === 'canvas-main') {
        if (this.userInfo) {
          activeWatermark(this.panelInfo.watermarkInfo.settingContent, this.userInfo, waterDomId, this.canvasId, this.panelInfo.watermarkOpen)
        } else {
          const method = this.userId ? proxyUserLoginInfo : userLoginInfo
          method().then(res => {
            this.userInfo = res.data
            activeWatermark(this.panelInfo.watermarkInfo.settingContent, this.userInfo, waterDomId, this.canvasId, this.panelInfo.watermarkOpen)
          })
        }
      }
    },
    isMainCanvas() {
      return this.canvasId === 'canvas-main'
    },
    triggerResetButton() {
      this.triggerSearchButton(true)
      this.$refs['viewWrapperChild']?.forEach(item => {
        if (item?.responseResetButton) {
          item.responseResetButton()
        }
      })
    },
    triggerSearchButton(isClear = false) {
      if (this.canvasId !== 'canvas-main') {
        return
      }
      const result = this.buildButtonFilterMap(this.$store.state.componentData, isClear)
      this.searchButtonInfo.autoTrigger = result.autoTrigger
      this.searchButtonInfo.filterMap = result.filterMap
      this.buttonFilterMap = this.searchButtonInfo.filterMap

      this.$store.state.componentData.forEach(component => {
        if (component.type === 'view' && this.buttonFilterMap[component.propValue.viewId]) {
          component.filters = this.buttonFilterMap[component.propValue.viewId]
        }
        if (component.type === 'de-tabs') {
          for (let idx = 0; idx < component.options.tabList.length; idx++) {
            const ele = component.options.tabList[idx].content
            if (!ele.type || ele.type !== 'view') continue
            ele.filters = this.buttonFilterMap[ele.propValue.viewId]
          }
        }
      })
    },
    buildButtonFilterMap(panelItems, isClear = false) {
      const result = {
        buttonExist: false,
        relationFilterIds: [],
        autoTrigger: true,
        filterMap: {}
      }
      if (!panelItems || !panelItems.length) return result
      let sureButtonItem = null
      result.buttonExist = panelItems.some(item => {
        if (item.type === 'custom-button' && item.serviceName === 'buttonSureWidget') {
          sureButtonItem = item
          return true
        }
      })

      if (!result.buttonExist) return result

      const customRange = sureButtonItem.options.attrs.customRange
      result.autoTrigger = sureButtonItem.options.attrs.autoTrigger
      const allFilters = panelItems.filter(item => item.type === 'custom')

      const matchFilters = customRange && allFilters.filter(item => sureButtonItem.options.attrs.filterIds.includes(item.id)) || allFilters

      result.relationFilterIds = matchFilters.map(item => item.id)

      let matchViewIds = []
      for (let index = 0; index < matchFilters.length; index++) {
        const item = matchFilters[index]
        if (!item.options.attrs.viewIds?.length) {
          matchViewIds = null
          break
        }
        matchViewIds = matchViewIds.concat(item.options.attrs.viewIds)
      }
      let viewKeyMap = buildViewKeyMap(panelItems)
      if (matchViewIds) {
        matchViewIds = [...new Set(matchViewIds)]
        const keys = Object.keys(viewKeyMap).filter(key => !matchViewIds.includes(key))
        keys.forEach(key => {
          delete viewKeyMap[key]
        })
      }
      viewKeyMap = this.buildViewKeyFilters(matchFilters, viewKeyMap, isClear)
      result.filterMap = viewKeyMap
      return result
    },
    buildViewKeyFilters(panelItems, result, isClear = false) {
      const wrapperChildAll = this.getAllWrapperChildRefs()
      if (!wrapperChildAll || !wrapperChildAll.length) return result
      panelItems.forEach((element) => {
        if (element.type !== 'custom') {
          return true
        }
        let wrapperChild
        wrapperChildAll?.forEach(item => {
          if (item?.['getComponentId'] && item.getComponentId() === element.id) {
            wrapperChild = item
          }
        })
        if (!wrapperChild || !wrapperChild.getCondition) return true
        let param = null
        if (isClear) {
          wrapperChild.clearHandler && wrapperChild.clearHandler()
        }
        param = wrapperChild.getCondition && wrapperChild.getCondition()
        const condition = formatCondition(param)
        let vValid = valueValid(condition)
        const required = element.options.attrs.required
        condition.requiredInvalid = required && !vValid
        condition['triggerId'] = uuid.v1()
        vValid = vValid || required
        const filterComponentId = condition.componentId
        const conditionCanvasId = wrapperChild.getCanvasId && wrapperChild.getCanvasId()
        Object.keys(result).forEach(viewId => {
          const vidMatch = viewIdMatch(condition.viewIds, viewId)
          const viewFilters = result[viewId]
          const canvasMatch = this.checkCanvasViewIdsMatch(conditionCanvasId, viewId)

          let j = viewFilters.length
          while (j--) {
            const filter = viewFilters[j]
            if (filter.componentId === filterComponentId) {
              viewFilters.splice(j, 1)
            }
          }
          canvasMatch && vidMatch && vValid && viewFilters.push(condition)
        })
      })
      return result
    },
    checkCanvasViewIdsMatch(conditionCanvasId, viewId) {
      if (conditionCanvasId === 'canvas-main') {
        return true
      }
      for (let index = 0; index < this.$store.state.componentData.length; index++) {
        const item = this.$store.state.componentData[index]
        if (item.type === 'view' && item.propValue.viewId === viewId && item.canvasId === conditionCanvasId) return true
      }
      return false
    },
    getComponentIndex(id) {
      for (let index = 0; index < this.componentData.length; index++) {
        const item = this.componentData[index]
        if (item.id === id) return index
      }
      return -1
    },
    _isMobile() {
      const flag = isMobile()
      this.terminal = flag ? 'mobile' : 'pc'
    },
    canvasStyleDataInit() {
      // 数据刷新计时器
      if (this.canvasStyleData.refreshViewEnable) {
        this.searchCount = 0
        this.timer && clearInterval(this.timer)
        let refreshTime = 300000
        if (this.canvasStyleData.refreshTime && this.canvasStyleData.refreshTime > 0) {
          if (this.canvasStyleData.refreshUnit === 'second') {
            refreshTime = this.canvasStyleData.refreshTime * 1000
          } else {
            refreshTime = this.canvasStyleData.refreshTime * 60000
          }
        }
        this.timer = setInterval(() => {
          this.clearAllLinkage()
          this.searchCount++
        }, refreshTime)
      }
    },
    clearAllLinkage() {
      this.$store.commit('clearPanelLinkageInfo')
      bus.$emit('clear_panel_linkage', { viewId: 'all' })
    },
    changeStyleWithScale,
    getStyle,
    restore() {
      const canvasHeight = document.getElementById(this.previewDomId).offsetHeight
      const canvasWidth = document.getElementById(this.previewDomId).offsetWidth
      this.scaleWidth = (canvasWidth) * 100 / (this.canvasStyleData.width - 8) // 获取宽度比
      // 如果是后端截图方式使用 的高度伸缩比例和宽度比例相同
      if (this.backScreenShot) {
        this.scaleHeight = this.scaleWidth
      } else {
        this.scaleHeight = canvasHeight * 100 / this.canvasStyleData.height// 获取高度比
      }
      if (this.isMainCanvas()) {
        this.$store.commit('setPreviewCanvasScale', {
          scaleWidth: (this.canvasStyleData.autoSizeAdaptor || this.terminal === 'mobile') ? (this.scaleWidth / 100) : 1,
          scaleHeight: (this.canvasStyleData.autoSizeAdaptor || this.terminal === 'mobile') ? (this.scaleHeight / 100) : 1
        })
      }
      this.handleScaleChange()
    },
    resetID(data) {
      if (data) {
        data.forEach(item => {
          item.type !== 'custom' && (item.id = uuid.v1())
        })
      }
      return data
    },
    format(value, scale) {
      return value * scale / 100
    },

    formatPoint(value, pointScale) {
      return value * pointScale
    },
    findSourceComponent(id) {
      return this.sourceComponentData.filter(element => element.id === id)[0]
    },
    handleScaleChange() {
      if (this.componentData) {
        const componentData = deepCopy(this.componentData)
        componentData.forEach(component => {
          if (component.type === 'custom' && !this._isMobile) {
            const sourceComponent = this.findSourceComponent(component.id)
            if (sourceComponent?.style) {
              component.style = deepCopy(this.findSourceComponent(component.id).style)
            }
          }
          Object.keys(component.style).forEach(key => {
            if (this.needToChangeHeight.includes(key)) {
              component.style[key] = this.format(component.style[key], this.scaleHeight)
            }
            if (this.needToChangeWidth.includes(key)) {
              component.style[key] = this.format(component.style[key], this.scaleWidth)
            }
            if (this.needToChangeInnerWidth.includes(key)) {
              if ((key === 'fontSize' || key === 'activeFontSize') && (this.terminal === 'mobile' || ['custom'].includes(component.type))) {
                // do nothing 移动端字符大小无需按照比例缩放，当前保持不变(包括 v-text 和 过滤组件)
              } else {
                component.style[key] = this.formatPoint(component.style[key], this.previewCanvasScale.scalePointWidth)
              }
            }
          })
          const maxWidth = this.canvasStyleData.width * this.scaleWidth / 100
          if (component.style['width'] > maxWidth) {
            component.style['width'] = maxWidth
          }
        })
        this.componentDataShow = componentData
        this.$nextTick(() => (eventBus.$emit('resizing', '')))
      }
    },
    openMessageLoading(cb) {
      const h = this.$createElement
      const iconClass = `el-icon-loading`
      const customClass = `de-message-loading de-message-export`
      this.$message({
        message: h('p', null, [
          this.$t('data_export.exporting'),
          h(
              Button,
              {
                props: {
                  type: 'text',
                },
                class: 'btn-text',
                on: {
                  click: () => {
                    cb()
                  }
                }
              },
              this.$t('data_export.export_center')
            ),
          this.$t('data_export.export_info')
        ]),
        iconClass,
        showClose: true,
        customClass
      })
    },
    openMessageSuccess(text, type, cb) {
      const h = this.$createElement
      const iconClass = `el-icon-${type || 'success'}`
      const customClass = `de-message-${type || 'success'} de-message-export`
      this.$message({
        message: h('p', null, [
          h('span', null, text),
          h(
            Button,
            {
              props: {
                type: 'text',
              },
              class: 'btn-text',
              on: {
                click: () => {
                  cb()
                }
              }
            },
            this.$t('data_export.export_center')
          )
        ]),
        iconClass,
        showClose: true,
        customClass
      })
    },
    exportData() {
      bus.$emit('data-export-center')
    },
    exportExcel() {
      this.$refs['userViewDialog-canvas-main'].exportExcel((val) => {
        if (val && val.success) {
          this.openMessageLoading(this.exportData)
        }

        if (val && val.success === false) {
          this.openMessageSuccess(`${this.showChartTableInfo.title ? this.showChartTableInfo.title : this.showChartTableInfo.name} 导出失败，前往`, 'error', this.exportData)
        }
        this.dialogLoading = false
      })
    },
    exportSourceDetails() {
      this.$refs['userViewDialog-canvas-main'].exportExcel((val) => {
        if (val && val.success) {
          this.openMessageLoading(this.exportData)
        }

        if (val && val.success === false) {
          this.openMessageSuccess(`${this.showChartTableInfo.title ? this.showChartTableInfo.title : this.showChartTableInfo.name} 导出失败，前往`, 'error', this.exportData)
        }
        this.dialogLoading = false
      })
    },
    exportViewImg() {
      this.imageDownloading = true
      this.$refs['userViewDialog-canvas-main'].exportViewImg(this.pixel, () => {
        this.imageDownloading = false
      })
    },
    deselectCurComponent(e) {
      if (!this.isClickComponent) {
        this.$store.commit('setCurComponent', { component: null, index: null })
      }
    },
    handleMouseDown() {
      this.$store.commit('setClickComponentStatus', false)
    },
    initMobileCanvas() {
      this.$store.commit('openMobileLayout')
    },
    canvasScroll() {
      // 当滚动距离超过 100px 时显示返回顶部按钮，否则隐藏按钮
      this.backToTopBtnShow = this.$refs[this.previewOutRefId].scrollTop > 200
      bus.$emit('onScroll')
    },
    initListen() {
      this.canvasMain = document.getElementById(this.previewDomId)
      // 监听主div变动事件
      if (this.canvasMain) {
        erd.uninstall(this.canvasMain)
        erd.listenTo(this.canvasMain, () => {
          this.$nextTick(() => {
            this.restore()
          })
        })
      }
      setTimeout(() => {
        // 监听画布div变动事件
        this.tempCanvas = document.getElementById(this.previewTempDomId)
        if (this.tempCanvas) {
          erd.uninstall(this.tempCanvas)
          erd.listenTo(document.getElementById(this.previewTempDomId), () => {
            this.$nextTick(() => {
              // 将mainHeight 修改为px 临时解决html2canvas 截图不全的问题
              this.mainHeight = this.tempCanvas.scrollHeight + 'px!important'
              this.mainHeightCount = this.tempCanvas.scrollHeight
              this.$emit('mainHeightChange', this.mainHeight)
            })
          })
        }
      }, 1500)
    },
    backToTop() {
      this.$refs[this.previewOutRefId].scrollTop = 0
    },
    downloadAsPDF() {
      this.dataLoading = true
      this.$emit('change-load-status', true)
      const domId = this.previewMainDomId
      setTimeout(() => {
        this.exporting = true
        this.backScreenShot = true
        const scrollHeight = document.getElementById('preview-temp-canvas-main').scrollHeight

        document.getElementById('preview-canvas-main').style.height = (scrollHeight + 'px')
        setTimeout(() => {
          html2canvas(document.getElementById(domId)).then(canvas => {
            const snapshot = canvas.toDataURL('image/jpeg', 1) // 是图片质量
            this.dataLoading = false
            this.$emit('change-load-status', false)
            this.exporting = false
            this.backScreenShot = false
            if (snapshot !== '') {
              this.snapshotInfo = snapshot
              this.pdfExportShow = true
            }
            if (this.$refs?.['link-opt-bar']) {
              this.$refs['link-opt-bar'].setWidgetStatus()
            }
          })
        }, 2500)
      }, 500)
    },
    closePreExport() {
      this.pdfExportShow = false
    },
    changePdfTemplate() {
      this.pdfTemplateContent = this.pdfTemplateAll[this.pdfTemplateSelectedIndex] ? this.pdfTemplateAll[this.pdfTemplateSelectedIndex].templateContent : ''
    },
    initPdfTemplate() {
      queryAll().then(res => {
        this.pdfTemplateAll = res.data
        this.changePdfTemplate()
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.bg {
  min-width: 200px;
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  background-size: 100% 100% !important;
}

.main-class {
  width: 100%;
  height: 100%;
  background-size: 100% 100% !important;
}

.custom-position {
  line-height: 30px;
  width: 100%;
  z-index: 100;
  height: 100%;
  text-align: center;
  cursor: not-allowed;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  flex-flow: row nowrap;
  color: #9ea6b2;
}

.dialog-css ::v-deep .el-dialog__title {
  font-size: 14px;
}

.dialog-css ::v-deep .el-dialog__header {
  padding: 40px 20px 0;
}

.dialog-css ::v-deep .el-dialog__body {
  padding: 10px 20px 20px;
}

::-webkit-scrollbar {
  width: 0px !important;
  height: 0px !important;
}

::v-deep .el-tabs__nav {
  z-index: 0;
}

</style>
